#ifndef __PATCHES_HPP__
#define __PATCHES_HPP__

#include "../tdp2/tdp2_vector.hpp"
#include "../tdp2/tdp2_math.hpp"
#include "bspfile.hpp"

namespace BSP2TMRF
{
	using namespace TDP::Math;
	using namespace TDP::Containers;
	using namespace RDX;
	using namespace BSPFile;

	struct PatchStitchPoint;
	struct PatchEvaluation;

	const float PatchLODScale_k = 0.05f;
	const float PatchLODBase_k = 1.0f;
	const float PatchLODTolerancePerLevel_k = 0.375f;


	struct StitchPointLOD
	{
		Vector<unsigned int> rowDivisions;
		Vector<unsigned int> colDivisions;
		bool aliasesPrevious;
		float lodMultiplier;
	};

	struct BSPPatchStitchPoint
	{
		unsigned int divisions;
		unsigned int vertStride;
		FVec3 positions[3];
		const BSPVertex_D *verts;

		struct BSPPatchStitchPoint *alias;		// Stitch point to propagate divisions to

		struct BSPPatchEvaluation *parent;

		void TouchDivisions(unsigned int d);
		void FindAlias(BSPPatchStitchPoint *sp, unsigned int numStitchPoints);
	};
	

	struct BSPPatchEvaluation
	{
		Vector<unsigned int> tris;
		Vector<BSPCommonVert> verts;

		BSPPatchStitchPoint *rowStitchPoints;
		BSPPatchStitchPoint *colStitchPoints;

		int cols;	// Columns in the CP grid
		int rows;	// Rows in the CP grid
		int totalCols;	// Columns in the subdivided point grid
		int totalRows;	// Rows in the subdivided point grid
		int numColStitchPoints;
		int numRowStitchPoints;

		FVec3 associatedMins;
		FVec3 associatedMaxs;

		FVec3 lodOrigin;
		StitchPointLOD lods[NumLODLevels_k];

		const BSPFace_D *face;

		void TouchBounds(const FVec3 &mins, const FVec3 &maxs);
	};

	struct PatchCalculator
	{
		Vector<BSPPatchStitchPoint> stitchPoints;
		Vector<BSPPatchEvaluation> patchEvals;
	};

	void ComputePatch(BSPPatchEvaluation *peval, const BSPVertex_D *cpVerts, int lod);

	void CalcPatchesForModel(PatchCalculator *pc,
		const BSPModel_D *model,
		const BSPFace_D *faces,
		const Vector<BSPVertex_D> &rawVerts,
		const Vector<BSPIndex_D> &meshVerts);
	float CompressSTVec(const FVec3 &normal, const FVec3 &svec, const FVec3 &tvec);
};

#endif
